<?php
namespace app\admin\logic;

use app\common\exception\LogicException;
use app\common\logic\CreateDirLogic;
use app\model\Machine;
use app\model\MachineVersion;
use think\File;
use ZipArchive;

class MachineVersionLogic
{
    //新增
    public function add(string $versionName, string $remark, File $file)
    {
        $machineVersionModel = new MachineVersion();
        //判断版本 
        $this->checkVersion($machineVersionModel, $versionName);

        //解压到指定文件夹
        $tmpPath = $file->getPathname();
        $zip = new ZipArchive();
        if ($zip->open($tmpPath) !== true) {
            throw new LogicException('打开文件失败');
        }

        // 对Zip文件进行解压缩操作
        $path = public_path(). 'storage/machine_version';
        $saveUrl = '/storage/machine_version/'. $versionName;
        $createDirLogic = new CreateDirLogic();
        $createDirLogic->toDo($path);

        $zip->extractTo($path);
        $zip->close();

        $machineVersionModel->insert([
            'version_name' => $versionName,
            'remark' => $remark,
            'url' => $saveUrl,
            'create_time' => request()->time(),
            'update_time' => request()->time(),
        ]);

        return true;
    }

    //判断版本
    public function checkVersion(MachineVersion $versionModel, string $versionName)
    {
        $versionInfo = $versionModel->field('version_name')
            ->where('delete_time', $versionModel::IS_DELETE_NO)
            ->order('id', 'desc')
            ->find();

        if (!$versionInfo) {
            return true;
        }

        $maxVersionFloat = round((float)$versionInfo['version_name'], 2);
        $versionNameFloat = round((float)$versionName, 2);
        if ($maxVersionFloat >= $versionNameFloat) {
            throw new LogicException('version_name必须大于'. $versionInfo['version_name']);
        }

        return true;
    }

    //列表
    public function getList(array $param)
    {
        $machineVersionModel = new MachineVersion();
        $query = $machineVersionModel->field('id,version_name,remark,url,create_time,update_time')
            ->where('delete_time', $machineVersionModel::IS_DELETE_NO);
            
        if ($param['version_name']) {
            $query->where('version_name', $param['version_name']);
        }

        return $query->order('id', 'desc')
            ->paginate([
                'list_rows' => $param['page_size'],
                'page' => $param['page'],
            ])
            ->toArray();
    }

    //删除
    public function del(int $id)
    {
        $machineVersionModel = new MachineVersion();
        $info = $machineVersionModel->field('id')
            ->where('id', $id)
            ->where('delete_time', $machineVersionModel::IS_DELETE_NO)
            ->find();
        if (!$info) {
            throw new LogicException('id不存在');
        }

        $machineVersionModel->where('id', $id)
            ->update([
                'delete_time' => request()->time()
            ]);

        return true;
    }

    //版本关联上位机
    public function machine(int $versionId, int $force, array $machineIds)
    {
        $machineVersionModel = new MachineVersion();
        $versionInfo = $machineVersionModel->field('id')
            ->where('id', $versionId)
            ->where('delete_time', $machineVersionModel::IS_DELETE_NO)
            ->find();
        if (!$versionInfo) {
            throw new LogicException('version_id不存在');
        }

        $machineModel = new Machine();
        $canMachineIds = $machineModel->whereIn('id', $machineIds)
            ->where('delete_time', $machineModel::IS_DELETE_NO)
            ->column('id');

        $updateData = [];
        foreach ($machineIds as $machineId) {
            if (!in_array($machineId, $canMachineIds)) {
                throw new LogicException('machine_id='. $machineId. '不存在');
            }
            $updateData[] = [
                'id' => $machineId,
                'target_version_id' => $versionId,
                'force' => $force,
            ];
        }

        $machineModel->saveAll($updateData);

        return true;
    }
}
